# fw_rules.py
import logging
import subprocess
from datetime import datetime

import win32com.client.gencache

from lib import Config


class RuleItem:
    def __init__(self, name):
        self.name = name
        self.value = {}
        self.keys = []
        self.ip_str = ''

    def __str__(self):
        return self.name + " : " + self.ip_str


class Rule:
    items = {
        "Action": 1,
        "ApplicationName": '',
        "Description": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "Direction": 1,
        "EdgeTraversal": False,
        "EdgeTraversalOptions": '0',
        "Enabled": True,
        "Grouping": '',
        "IcmpTypesAndCodes": '',
        "InterfaceTypes": 'All',
        "Interfaces": None,
        "LocalAddresses": '*',
        "LocalAppPackageId": '',
        "LocalPorts": Config.Hall_Port,
        "LocalUserAuthorizedList": '',
        "LocalUserOwner": '',
        "Name": '0_unset_name',
        "Profiles": 2147483647,
        "Protocol": 6,
        "RemoteAddresses": '192.168.1.0/24',
        "RemoteMachineAuthorizedList": '',
        "RemotePorts": '*',
        "RemoteUserAuthorizedList": '',
        # "SecureFlags": '0',
        "serviceName": ''}
    # 中英文转换
    # items_name = {
    #     "Action": '操作',
    #     "ApplicationName": '程序',
    #     "Description": '描述',
    #     "Direction": '进站/出站',
    #     "EdgeTraversal": '边缘穿越',
    #     "EdgeTraversalOptions": '边缘穿越选项',
    #     "Enabled": '已启用',
    #     "Grouping": '组',
    #     "IcmpTypesAndCodes": 'ICMP设置',
    #     "InterfaceTypes": '接口类型',
    #     "Interfaces": '接口',
    #     "LocalAddresses": '本地地址',
    #     "LocalAppPackageId": '应用程序包',
    #     "LocalPorts": '本地端口',
    #     "LocalUserAuthorizedList": '授权的本地计算机',
    #     "LocalUserOwner": '本地用户所有者',
    #     "Name": '名称',
    #     "Profiles": '配置文件',
    #     "Protocol": '协议',
    #     "RemoteAddresses": '远程地址',
    #     "RemoteMachineAuthorizedList": '授权的远程计算机',
    #     "RemotePorts": '远程端口',
    #     "RemoteUserAuthorizedList": '授权的远程用户',
    #     "SecureFlags": '安全',
    #     "serviceName": '服务名'}
    items_shell = {
        "Action": 'action',
        "ApplicationName": 'program',
        "Description": 'description',
        "Direction": 'dir',
        "EdgeTraversal": 'edge',
        "EdgeTraversalOptions": '边缘穿越选项',
        "Enabled": 'enable',
        "Grouping": '组',
        "IcmpTypesAndCodes": 'ICMP设置',
        "InterfaceTypes": 'interfacetype',
        "Interfaces": '接口',
        "LocalAddresses": 'localip',
        "LocalAppPackageId": '应用程序包',
        "LocalPorts": 'localport',
        "LocalUserAuthorizedList": '授权的本地计算机',
        "LocalUserOwner": '本地用户所有者',
        "Name": 'name',
        "Profiles": 'profile',
        "Protocol": 'protocol',
        "RemoteAddresses": 'remoteip',
        "RemoteMachineAuthorizedList": 'rmtcomputergrp',
        "RemotePorts": 'remoteport',
        "RemoteUserAuthorizedList": 'rmtusrgrp',
        "SecureFlags": 'security',
        "serviceName": 'service'
    }

    def __init__(self, index):
        self.index = index
        # for i in self.items_name.keys():
        #     self.items[i] = ''

    def init_by_dict(self, dirc_con):
        for key in dirc_con.keys():
            self.items[key] = dirc_con[key]

    def create_rule(self):
        app = win32com.client.Dispatch('HNetCfg.FwRule')
        # 注意赋值顺序
        app.Action = int(self.items["Action"])
        app.Description = self.items["Description"]
        app.Direction = int(self.items["Direction"])
        app.EdgeTraversal = self.items["EdgeTraversal"]
        # app.EdgeTraversalOptions = self.items["EdgeTraversalOptions"]
        app.Enabled = self.items["Enabled"]
        app.Grouping = ""  # self.items["Grouping"]
        # app.IcmpTypesAndCodes = self.items["IcmpTypesAndCodes"]
        app.InterfaceTypes = self.items["InterfaceTypes"]
        # app.Interfaces = self.items["Interfaces"]
        app.LocalAddresses = self.items["LocalAddresses"]
        app.LocalAppPackageId = self.items["LocalAppPackageId"]
        # app.LocalPorts = str(self.items["LocalPorts"]),
        # app.LocalUserAuthorizedList = self.items["LocalUserAuthorizedList"]
        app.LocalUserOwner = self.items["LocalUserOwner"]
        app.Name = self.items["Name"]
        app.Profiles = self.items["Profiles"]
        app.Protocol = self.items["Protocol"]
        app.RemoteAddresses = self.items["RemoteAddresses"]
        # app.RemoteMachineAuthorizedList = self.items["RemoteMachineAuthorizedList"]
        app.RemotePorts = self.items["RemotePorts"]
        app.LocalPorts = self.items['LocalPorts']
        # app.RemoteUserAuthorizedList = ''
        # app.SecureFlags = self.items["SecureFlags"]
        # app.serviceName = ""
        # app.ApplicationName = ""
        return app

    def __str__(self):
        result = "=" * 10 + '\n序号 : ' + str(self.index) + '\n'
        for key in self.items.keys():
            result += key + " : " + str(self.items[key]) + "\n"
        return result


def add_rule(dict_value):
    cmd = f'netsh advfirewall firewall add rule name="%s" dir=in action=allow protocol=TCP localport=%s remoteip=%s' % (
        dict_value['Name'], Config.Hall_Port, dict_value['RemoteAddresses'])
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out = process.wait()
    logging.info("create rule:name=%s, return %s", dict_value['Name'], out)
    if out == 0:
        fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
        apps = fw.Rules
        for app in apps:
            if app.Name == dict_value['Name']:
                app.Grouping = dict_value['Grouping']
                break
    # out, error = process.communicate()
    # if out:
    #     print(out.decode('gbk'))
    # if error:
    #     print(error.decode('gbk'))
    # fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
    # apps = fw.Rules
    # print(apps.Count)
    # # app = win32com.client.Dispatch('HNetCfg.FwRule3')
    # rule_obj = rule(-1)
    # rule_obj.init_by_dict(dict_value)
    # app = rule_obj.create_rule()
    # print('add', app.Name, app.Grouping)
    # apps.Add(app)


def del_rule(dict_value):
    fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
    apps = fw.Rules

    rule_obj = Rule(-1)
    rule_obj.init_by_dict(dict_value)
    for app in apps:
        if rule_obj.items['Name'] == str(app.Name) and rule_obj.items['LocalPorts'] == str(app.LocalPorts) and \
                rule_obj.items['RemoteAddresses'] == str(app.RemoteAddresses):
            # 只能根据Name删除,大概是个傻子哟
            logging.info("del rule:", str(app.Name))
            apps.Remove(str(app.Name))
            # break


# 根据分组名称删除分组
def del_rule_by_group(group_name: str):
    fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
    apps = fw.Rules

    for app in apps:
        if group_name == str(app.Grouping):
            apps.Remove(str(app.Name))
            logging.info("del rule by group: %s group (%s)", str(app.Name), group_name)


# 根据分组名称重命名分组
def rename_group(old_name: str, new_name: str):
    fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
    apps = fw.Rules
    count = 0
    for app in apps:
        if old_name == str(app.Grouping):
            app.Grouping = new_name
            count += 1
            logging.info("rename :name=%s,group=%s", app.Name, app.Grouping)
    logging.info("rename_group :%d", count)


# 修改远程地址
def change_rule_addr(name: str, remote_address: str):
    fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
    apps = fw.Rules
    logging.info('change rule addr %s', name)
    count = 0
    for app in apps:
        if name == str(app.Name):
            logging.info('change rule addr %s', app.RemoteAddresses)
            logging.info('change rule >>>> %s', remote_address)
            app.RemoteAddresses = remote_address
            count += 1
    if count > 0:
        logging.info('change rule addr %s number %d', name, count)
    else:
        logging.error('change rule addr %s number %d', name, count)
# def get_rules():
#     fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
#     apps = fw.Rules
#     print(apps.Count)
#     for app in apps:
#         print(app.Name)

# if __name__ == '__main__':
#     my_dict = {
#         'Name': 'auto_firewall_0',
#         'RemoteAddresses': '192.168.1.0/24,192.168.31.0/24',
#         'Grouping': 'auto_firewall'
#     }
#     add_rule(my_dict)
#     # del_rule(my_dict)
